﻿using DrawIO45.Models.DrawIOs;
using DrawIO45.Models.Logic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace DrawIO45.Draws.Business
{
    internal class DrawItem : IDrawOnRoot
    {
        public const int ItemCellHeight = DrawHelper.ItemCellHeight;

        DrawItemOption Option;

        public DrawItem()
        {
            Option = new DrawItemOption();
        }

        public DrawItem(DrawItemOption option)
        {
            Option = option;
        }

        public void DrawOnRoot(Root root, List<DILocationInfo<LClassInfo>> classInfos)
        {
            // 划出基本类图
            for (int i = 0; i < classInfos.Count; i++)
            {
                var itemClassInfo = classInfos[i];
                var itemId = itemClassInfo.Object.Id;

                var itemType = itemClassInfo.Object.Source;

                if (FilterOption(itemClassInfo.Object) != true)
                    continue;

                // 增加外壳
                root.MxCells.Add(new MxCell
                {
                    Id = itemId,
                    Parent = "1",
                    Style = "swimlane;fontStyle=0;childLayout=stackLayout;horizontal=1;startSize=26;fillColor=none;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;whiteSpace=wrap;html=1;",
                    Vertex = "1",
                    Value = itemClassInfo.Object.GetFormatName(),

                    MxGeometries = new List<MxGeometry>
                    {
                        new MxGeometry
                        {
                            As = "geometry",
                            Width = itemClassInfo.Size.Width.ToString(),
                            Height = itemClassInfo.Size.Height.ToString(),
                            X = itemClassInfo.Point.X.ToString(),
                            Y = itemClassInfo.Point.Y.ToString(),
                        },
                    }
                });

                var properties = itemClassInfo.Object.Properties ?? new List<LPropertyInfo>();

                var subItemHeight = ItemCellHeight;   // 表头也算一个

                for (int p = 0; p < properties.Count; p++)
                {
                    var itemInfo = properties[p];
                    var methodId = itemInfo.Id;

                    root.MxCells.Add(new MxCell
                    {
                        Id = methodId,
                        Parent = itemId,
                        Style = "text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;",
                        Vertex = "1",
                        Value = BuildHtmlText(itemInfo.GetFormatName()),

                        MxGeometries = new List<MxGeometry>
                        {
                            new MxGeometry
                            {
                                As = "geometry",
                                Width = itemClassInfo.Size.Width.ToString(),
                                Height = ItemCellHeight.ToString(),
                                Y = subItemHeight.ToString(),
                            },
                        }

                    });
                    subItemHeight += ItemCellHeight;
                }

                // 在这里加横线
                root.MxCells.Add(new MxCell
                {
                    Id = DrawHelper.GetRandomId(),
                    Parent = itemId,
                    Style = "line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;",
                    Vertex = "1",

                    MxGeometries = new List<MxGeometry>
                    {
                        new MxGeometry
                        {
                            As = "geometry",
                            Width = itemClassInfo.Size.Width.ToString(),
                            Height = ItemCellHeight.ToString(),
                            Y = subItemHeight.ToString(),
                        },
                    }
                });

                subItemHeight += 8;

                var methodInfos = itemClassInfo.Object.MethodInfos ?? new List<LMethodInfo>();

                // 增加内容
                for (int m = 0; m < methodInfos.Count; m++)
                {
                    var itemMethodInfo = methodInfos[m];
                    var methodId = itemMethodInfo.Id;

                    root.MxCells.Add(new MxCell
                    {
                        Id = methodId,
                        Parent = itemId,
                        Style = "text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;whiteSpace=wrap;html=1;",
                        Vertex = "1",
                        Value = BuildHtmlText(itemMethodInfo.GetFormatName()),

                        MxGeometries = new List<MxGeometry>
                        {
                            new MxGeometry
                            {
                                As = "geometry",
                                Width = itemClassInfo.Size.Width.ToString(),
                                Height = ItemCellHeight.ToString(),
                                Y = subItemHeight.ToString(),
                            },
                        }
                    });

                    subItemHeight += ItemCellHeight;
                }
            }
        }

        bool FilterOption(LClassInfo classInfo)
        {
            Type type = classInfo.Source;
            if (type.IsInterface)
            {
                if (Option.AllowUseTypes?.Contains(AllowUseType.Inteface) != true)
                    return false;
            }


            if (type.IsClass)
            {
                if (Option.AllowUseTypes?.Contains(AllowUseType.Class) != true)
                    return false;

                if (Option.DrawModel != true)
                {
                    if (classInfo.MethodInfos?.Any() != true)
                        return false;
                }
            }

            return true;
        }

        public static string BuildHtmlText(string text)
        {
            return HttpUtility.HtmlEncode(text);
        }
    }

    public class DrawItemOption
    {
        public bool DrawModel { get; set; } = true;

        public AllowUseType[] AllowUseTypes { get; set; } = new AllowUseType[]
        {
            AllowUseType.Class,
            AllowUseType.Inteface,
        };
    }
}
